/* main.c -- MQTT client example
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "mqtt.h"
#include "wifi.h"
#include "config.h"
#include "debug.h"
#include "gpio.h"
#include "user_interface.h"
#include "mem.h"
/*该节点识别码*/
//DOOR STAIRS BED BOOK
const char  *module_code = "STAIRS";
/*主机识别码*/
//DOOR_host STAIRS_host BED_host BOOK_host
char *host_code = "STAIRS_host";

typedef enum
{
	CLOSE=0,
	OPEN=1
}SwStu;

struct	//设备状态
{
	SwStu MOS1:1;
	SwStu MOS2:1;
	SwStu Task1SendClock:1;		//Task1接收消息锁
	SwStu NetworkClock:1;		//网络锁，网络连接成功后OPEN
	u16   RebootDelay;			//重启倒计时
}deviceState={CLOSE,CLOSE,OPEN,CLOSE,0};

//GPIO端口号-输出控制
#define MOS1GPIO	GPIO_ID_PIN(14)
#define MOS2GPIO 	GPIO_ID_PIN(12)
#define LEDGPIO		GPIO_ID_PIN(0)
#define BORUDLED	GPIO_ID_PIN(2)
//GPIO端口号-外部中断
#define SENSER1GPIO BIT5
#define SENSER2GPIO BIT4

//建立消息队列
os_event_t   Task1Queue;

static MQTT_Client mqttClient;
void user_gpio_config();
void wifiConnectCb(uint8_t status)
{
	if(status == STATION_GOT_IP){
		MQTT_Connect(&mqttClient);
	} else {
		MQTT_Disconnect(&mqttClient);
	}
}
void mqttConnectedCb(uint32_t *args)
{
	INFO("MQTT: Connected\r\n");
	deviceState.NetworkClock = OPEN;
	MQTT_Subscribe((MQTT_Client*)args, host_code, 0);
	MQTT_Publish((MQTT_Client*)args, module_code, "Start", sizeof("Start"), 0, 0);
	user_gpio_config();
}

void mqttDisconnectedCb(uint32_t *args)
{
	MQTT_Client* client = (MQTT_Client*)args;
	INFO("MQTT: Disconnected\r\n");
	deviceState.NetworkClock = CLOSE;
}

void mqttPublishedCb(uint32_t *args)
{
	MQTT_Client* client = (MQTT_Client*)args;
	INFO("MQTT: Published\r\n");
}

void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
	char *topicBuf = (char*)os_zalloc(topic_len+1),
			*dataBuf = (char*)os_zalloc(data_len+1);

	MQTT_Client* client = (MQTT_Client*)args;

	os_memcpy(topicBuf, topic, topic_len);
	topicBuf[topic_len] = 0;

	os_memcpy(dataBuf, data, data_len);
	dataBuf[data_len] = 0;

	INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf);

	if(os_strcmp(topicBuf, host_code) != 0){
		INFO("Topic error\n");
		goto error;
	}
	if(os_strcmp(dataBuf, "CM1_OP") == 0)
	{
		GPIO_OUTPUT_SET(MOS1GPIO, OPEN);
		INFO("MOS1 OPEN\n");
	}else if(os_strcmp(dataBuf, "CM1_CL") == 0)
	{
		GPIO_OUTPUT_SET(MOS1GPIO, CLOSE);
		INFO("MOS1 CLOSE\n");
	}else if(os_strcmp(dataBuf, "CM2_OP") == 0)
	{
		GPIO_OUTPUT_SET(MOS2GPIO, OPEN);
		INFO("MOS2 OPEN\n");
	}else if(os_strcmp(dataBuf, "CM2_CL") == 0)
	{
		GPIO_OUTPUT_SET(MOS2GPIO, CLOSE);
		INFO("MOS2 CLOSE\n");
	}


	error:	os_free(topicBuf);
			os_free(dataBuf);
}


/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
 *******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;
    
    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;
            
        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;
            
        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;
            
        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;
            
        default:
            rf_cal_sec = 0;
            break;
    }
    
    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR
Task1(os_event_t * event)
{
	os_printf("sig:%d\n", event->sig);
//	if(deviceState.NetworkClock == CLOSE)return;
	//os_delay_us(100000);
	switch(event->sig)
		{
		case SENSER1GPIO:
			os_printf("GPIO_ID_PIN5 = %d\n", GPIO_INPUT_GET(GPIO_ID_PIN(5)));
//			if(0 == GPIO_INPUT_GET(GPIO_ID_PIN(5)))
//			{
				MQTT_Publish(&mqttClient, module_code, "S1_TRIG", sizeof("S1_TRIG"), 0, 0);
				os_printf("GPIO5 LOW\n");
//			}
			break;
		case SENSER2GPIO:
			os_printf("GPIO_ID_PIN4 = %d\n", GPIO_INPUT_GET(GPIO_ID_PIN(4)));
//			if(0 == GPIO_INPUT_GET(GPIO_ID_PIN(4)))
//			{
				MQTT_Publish(&mqttClient, module_code, "S2_TRIG", sizeof("S2_TRIG"), 0, 0);
				os_printf("GPIO4 LOW\n");
//			}
			break;
		case DEVICE_KEEPALIVE:
				MQTT_Publish(&mqttClient, module_code, "KEEPALIVE", sizeof("KEEPALIVE"), 0, 0);
			break;
		default:
			os_printf("Task1 quit\n");
			break;
	}
	deviceState.Task1SendClock = OPEN;
}

/*GPIO外部中断处理函数
*
*/
void ICACHE_FLASH_ATTR
user_gpio_cb(void *arg)
{
	volatile uint32 i,j;
	uint32 gpio_status;
	if(deviceState.NetworkClock == CLOSE){
		os_printf("NetWork not connect\n");
		return;
	}
	os_delay_us(20000);
	gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
	if((SENSER1GPIO == gpio_status) && (0 == GPIO_INPUT_GET(GPIO_ID_PIN(5))))
	{
			if(deviceState.Task1SendClock == OPEN){
			deviceState.Task1SendClock = CLOSE;
			system_os_post (0,SENSER1GPIO, 0);
			os_printf("SENSER1GPIO\n");
		}
	}else if((SENSER2GPIO == gpio_status) && (0 == GPIO_INPUT_GET(GPIO_ID_PIN(4))))
	{
			if(deviceState.Task1SendClock == OPEN){
			deviceState.Task1SendClock = CLOSE;
			system_os_post (0,SENSER2GPIO, 0);
			os_printf("SENSER2GPIO\n");
		}
	}
	GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS,gpio_status);
}

/*GPIO管脚配置
*
*/
void ICACHE_FLASH_ATTR
user_gpio_config()
{
	PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO4_U);	//上啦
	PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO5_U);

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//IO输出
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U,FUNC_GPIO0);//LED
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);//borudLED

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);//外部中断输入
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);
	GPIO_OUTPUT_SET(MOS1GPIO, CLOSE);				//默认配置为低电平
	GPIO_OUTPUT_SET(MOS2GPIO, CLOSE);
	//GPIO4 5配置为外部中断
	ETS_GPIO_INTR_ATTACH(user_gpio_cb,NULL);
	gpio_pin_intr_state_set(GPIO_ID_PIN(4),GPIO_PIN_INTR_NEGEDGE);
	gpio_pin_intr_state_set(GPIO_ID_PIN(5),GPIO_PIN_INTR_NEGEDGE);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(5), 0);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(4), 0);
	ETS_GPIO_INTR_ENABLE();
	os_printf("GPIO Creation Succeed!\n");
}

/*网络初始化*/
void ICACHE_FLASH_ATTR
user_network_init()
{
	CFG_Load();
	MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.security);
	MQTT_InitClient(&mqttClient, sysCfg.device_id, sysCfg.mqtt_user, sysCfg.mqtt_pass, sysCfg.mqtt_keepalive, 1);
	MQTT_OnConnected(&mqttClient, mqttConnectedCb);
	MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
	MQTT_OnPublished(&mqttClient, mqttPublishedCb);
	MQTT_OnData(&mqttClient, mqttDataCb);

	WIFI_Connect(sysCfg.sta_ssid, sysCfg.sta_pwd, wifiConnectCb);
}


void user_init(void)
{
	uart_init(BIT_RATE_115200, BIT_RATE_115200);
	user_network_init();
	system_os_task(Task1,0,&Task1Queue,2);
	os_delay_us(1000000);
	INFO("\r\nSystem started ...\r\n");

}
